#ifndef __CAN_H__
#define __CAN_H__

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "list.h"
#include "lock.h"
#include "wait.h"
#include "log.h"

#include <stdio.h>
#include <unistd.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <sys/prctl.h>

struct can;

enum CAN_EVENT
{
    CAN_EVENT_NONE = 0,
    CAN_EVENT_TEST,
    CAN_EVENT_MAX,
};

typedef int32_t (*can_event_notify)(struct can*, int32_t, void*, void*);

struct can_event_action
{
    can_event_notify notify;
    void* object;
    struct can_event_action* next;
};

struct can_operation
{
    int32_t (*init)(struct can*);
    int32_t (*release)(struct can*);

    int32_t (*open)(struct can*);
    int32_t (*close)(struct can*);

    int32_t (*write)(struct can*, uint8_t*, uint32_t);

    int32_t (*register_notify)(struct can*, int32_t, can_event_notify notify, void*);
    int32_t (*unregister_notify)(struct can*, int32_t, void*);
    int32_t (*trigger_notify)(struct can*, int32_t, void*);
};

struct can
{
    struct list_head head;
    wait_t wait;
    lock_t lock;
    lock_t notify_lock;

    int running_flag;
    pthread_t pid;

    int opened;

    int socket;
    struct sockaddr_can addr;
	struct ifreq ifr;

    struct can_frame frame;
    struct can_filter rfilter[1];

    char *dev;

    struct can_operation* op;
    struct can_event_action *paction[CAN_EVENT_MAX];
};

int32_t create_init_can(struct can** pcan);
void release_destroy_can(struct can* pcan);
        
#endif
